﻿using System;
using System.Data;
using System.Data.SqlClient;

namespace SqlMyReplicationModule
{
    /// <summary>
    /// Beinhaltet alle wichtigen Verbindungsinformationen über unseren aktuellen Replikationsvorgang.
    /// Und die basis SQL Ausführungsfunktionen um eine Datatable zu erhalten oder einen SQL String auszuführen.
    /// </summary>
    public class SqlReplicationConnection
    {
        #region Properties
        public enum RepType
        {
            Subscriber,
            Publisher
        }

        /// <summary>
        /// Der Pfad zum Publisher Replication DBServer z.B. Replication01\SQL2008R2STD
        /// </summary>
        public string Publisher { get; set; }

        /// <summary>
        /// Der Pfad zum Subscriber Replication DBServer z.B. Replication01\SQL2008R2Exp
        /// </summary>
        public string Subscriber { get; set; }

        /// <summary>
        /// Der Pfad zum Main Replication DBServer z.B. Replication01\SQL2008R2STD 
        /// </summary>
        public string Distributor { get; set; }

        /// <summary>
        /// Der Name der Publisher Datenbank
        /// </summary>
        public string PublisherDb { get; set; }

        /// <summary>
        /// Der Name der Subscriber Datenbank
        /// </summary>
        public string SubscriberDb { get; set; }

        /// <summary>
        /// Der Name der Tabelle die aktuell überprüft wird.
        /// </summary>
        public string ArticleName { get; set; }
        #endregion

        #region Konstruktor
        public SqlReplicationConnection(string publisher, string subscriber, string distributor, string publisherDb, string subscriberDb, string articleName)
        {
            Publisher = publisher;
            Subscriber = subscriber;
            Distributor = distributor;
            PublisherDb = publisherDb;
            SubscriberDb = subscriberDb;
            ArticleName = articleName;
        }
        #endregion

        #region Public Functions
        /// <summary>
        /// Gibt den GetConnectionstring für den passenden Publisher zurück
        /// </summary>
        /// <returns></returns>
        public string PublisherConnectionString()
        {
            return string.Format("Data Source='{0}';Initial Catalog='{1}';Integrated Security=SSPI", Publisher, PublisherDb);
        }

        /// <summary>
        /// Gibt den GetConnectionstring für den passenden Subscriber zurück
        /// </summary>
        /// <returns></returns>
        public string SubScriberConnectionString()
        {
            return string.Format("Data Source='{0}';Initial Catalog='{1}';Integrated Security=SSPI", Subscriber, SubscriberDb);
        }

        /// <summary>
        /// Lädt das übergebene Select Statement in eine DataTable
        /// </summary>
        /// <param name="sqlString">SQL-AbfrageString (Select)</param>
        /// <returns>DataTable mit Daten | Null-> Wenn ein Fehler aufgetreten ist.</returns>
        public DataTable GetDataTable(string sqlString, RepType repType)
        {
            DataTable dataTable = new DataTable();
            using (SqlConnection sqlCon = new SqlConnection(GetConnectionstring(repType)))
            {
                try
                {
                    SqlCommand sqlCommand = new SqlCommand(sqlString);
                    SqlDataAdapter dataAdapter = new SqlDataAdapter(sqlCommand);

                    sqlCommand.Connection = sqlCon;
                    sqlCon.Open();
                    //Auslesen der Daten und in die DataTable schreiben
                    dataAdapter.Fill(dataTable);
                }
                catch (Exception exception)
                {
                    dataTable = null;
                }
                finally
                {
                    sqlCon.Close();
                }
            }

            return dataTable;
        }

        /// <summary>
        /// SQL-Abfrage Klasse, an diese Klasse wird nur der SQL String übergeben, welcher nur ein Eindeutiges Ergebnis liefert und man erhält das Ergebnis als String zurück.
        /// </summary>
        /// <param name="sqlString">SQL-AbfrageString (Select)</param>
        /// <returns>String (Einzelnen Wert)</returns>
        public string GetString(string sqlString, RepType repType)
        {
            string str = string.Empty;
            using (SqlConnection sqlCon = new SqlConnection(GetConnectionstring(repType)))
            {
                try
                {
                    SqlCommand sqlCommand = new SqlCommand(sqlString);
                    sqlCommand.Connection = sqlCon;
                    sqlCon.Open();
                    str = Convert.ToString(sqlCommand.ExecuteScalar());
                }
                catch (Exception exception)
                {
                    str = string.Empty;
                }
                finally
                {
                    sqlCon.Close();
                }
            }

            return str;
        }

        /// <summary>
        /// Ausführen des übergebenen SQL Strings
        /// </summary>
        /// <returns>TRUE->Erfolgreich ausgeführt | FALSE->Fehler beim Ausführen</returns>
        public Boolean ExecuteSql(string sqlString, RepType repType)
        {
            SqlConnection sqlConnection = null;
            SqlCommand sqlCommand = null;

            try
            {
                //Anlegen der Tabellen auf der aktuellen vom User angegebenen Datenbank, die Verbindung muss auf die "leere" Db erfolgen, da sonst ein Fehler kommt.
                sqlConnection = new SqlConnection(GetConnectionstring(repType));
                sqlCommand = new SqlCommand(sqlString, sqlConnection);
                sqlConnection.Open();
                sqlCommand.ExecuteNonQuery();
                return true;
            }
            catch (Exception exception)
            {
                return false;
            }
            finally
            {
                if (sqlConnection != null)
                {
                    sqlConnection.Close();
                }
            }
        }
        #endregion

        #region Private Functions
        /// <summary>
        /// Gibt den passenden GetConnectionstring anhand des übergeben Typs zurück.
        /// </summary>
        private string GetConnectionstring(RepType repType)
        {
            //Den passenden GetConnectionstring laden.
            string connectionString = PublisherConnectionString();
            if (repType == RepType.Subscriber)
            {
                connectionString = SubScriberConnectionString();
            }

            return connectionString;
        }
        #endregion
    }
}
